home *** CD-ROM | disk | FTP | other *** search
/ Mac Magazin/MacEasy 22 / Mac Magazin and MacEasy Magazine CD - Issue 22.iso / System / Systemerweiterungen / NoPowerOffKey 1.2 / PatchPowerOff.c < prev    next >
C/C++ Source or Header  |  1996-05-09  |  6KB  |  212 lines

  1. /*
  2. **    Apple Macintosh Developer Technical Support
  3. **
  4. **    Sample code demonstrating how to patch PowerOff key
  5. **
  6. **    by Brian Bechtel, Apple Developer Technical Support
  7. **
  8. **    File:        PatchPowerOff.c
  9. **
  10. **    Copyright © 1995 Apple Computer, Inc.
  11. **    All rights reserved.
  12. **
  13. **    You may incorporate this sample code into your applications without
  14. **    restriction, though the sample code has been provided "AS IS" and the
  15. **    responsibility for its operation is 100% yours.  However, what you are
  16. **    not permitted to do is to redistribute the source as "DTS Sample Code"
  17. **    after having made changes. If you're going to re-distribute the source,
  18. **    we require that you make it clear in the source that the code was
  19. **    descended from Apple Sample Code, but that you've made changes.
  20. */
  21. #include <Gestalt.h>
  22. #include <Resources.h>
  23. #include <Errors.h>
  24. #include <OSUtils.h>
  25. #include <Traps.h>
  26. #include <SetupA4.h>
  27. #include <A4Stuff.h>
  28.  
  29. /* from technote 1017, "System 7.5.3"  Thanks to John Montbriand for pointing
  30.  * out that I'd used a seed release of the technote, which didn't include in
  31.  * the UPP definition any space for the result of the call.
  32.  */
  33. #ifdef PowerPC
  34. enum {
  35.     uppPowerOffProcInfo = kPascalStackBased
  36.         | RESULT_SIZE(SIZE_CODE(sizeof(OSErr))) /* space for result */
  37.         | STACK_ROUTINE_PARAMETER(1, kTwoByteCode)
  38.         | STACK_ROUTINE_PARAMETER(2, kTwoByteCode)
  39. };
  40. #endif
  41.  
  42. /* constants used as parameters to the power off key routine */
  43. enum {
  44.     kPowerKey  = 0x7F,
  45.     kDissablePwKy = 0x6B,
  46.     kEnablePwKy = 0x00,
  47.  
  48.     kShutdownDlog = 0x7E,
  49.     kNoDismiss = 0x00,
  50.     kOneSecond = 0x70,
  51.     kTenSeconds = 0x400
  52. };
  53.  
  54. /* declaration for the power off key routine */
  55. typedef pascal OSErr (*PwrKeyProc)(short item, short action);
  56.  
  57. /* for debugging */
  58. #define assert(i) if ((i) DebugStr("\p;printf \"assertion failed file %s line %d\" __FILE__, __LINE__")
  59.  
  60. #define kINITid            0    /* matches the resID in the 68K Project preferences */
  61. #define kICONid            128
  62.  
  63. pascal void ShowIcon7(short iconId, Boolean advance);
  64.  
  65. // local function declarations
  66. void InitAlertPatch(void);
  67. void ClearAlertPatch(void);
  68. void asm AlertPatch(void);
  69. OSErr DisablePowerOffKey(void);
  70. void main(void);
  71.  
  72. static long        gOriginalTrapPtr = 0;
  73. static Boolean    gAlertPatchIsInstalled = false;
  74.  
  75. /*
  76.  * InstallAlertPatch
  77.  * This routine patches the Alert() trap so that we can check for
  78.  * the PowerOff alert and dismiss it before it comes up.
  79.  */
  80. void InitAlertPatch(void)
  81. {
  82.     if (gAlertPatchIsInstalled == false)
  83.     {
  84.         gOriginalTrapPtr = (long) NGetTrapAddress( _Alert, ToolTrap);
  85.         NSetTrapAddress( (UniversalProcPtr)(AlertPatch), _Alert, ToolTrap);
  86.         gAlertPatchIsInstalled = true;
  87.     }
  88. }
  89.  
  90. /*
  91.  * ClearAlertPatch
  92.  * This routine clears out the patch we installed in InstallAlertPatch.
  93.  * Note: Never call this routine from within an extension; you don't know
  94.  * what other patches may have been put on Alert() after you installed
  95.  * your patch, and bad things would happen if you eliminate yourself from
  96.  * the chain of patches...
  97.  */
  98. void ClearAlertPatch(void)
  99. {
  100.     if (gAlertPatchIsInstalled == true)
  101.     {
  102.         NSetTrapAddress( (UniversalProcPtr)(gOriginalTrapPtr), _Alert, ToolTrap);
  103.         gAlertPatchIsInstalled = false;
  104.     }
  105. }
  106.  
  107. /*
  108.  * AlertPatch
  109.  * This patch checks to see if we are about to display alert -16500.  This
  110.  * is the ALRT id used by the dialog which asks if you want to shutdown, etc.
  111.  * If we are about to show that dialog, fake things up as if we have already
  112.  * shown the dialog, and the user has pressed the Cancel button.  The result
  113.  * is that the dialog is never shown, and no action is taken.  Just as if
  114.  * the PowerOff code was never added to the system...
  115.  * Call this routine only if the programmatic method (using the 'pwky' Gestalt
  116.  * selector) fails.
  117.  * This patch trashes register a0 and possibly register d0, but
  118.  * these registers are trashed by Alert anyway.
  119.  */
  120. void asm AlertPatch(void)
  121. {
  122. // Check for proper alert.  If it's the trap we want to avoid,
  123. // return to caller without actually executing the Alert trap.
  124. // Set up the stack so it looks as if the user hit okay.
  125.  
  126. PatchPowerOff:
  127. // test for specific PowerOff dialog id.  If we find it, return as if we hit cancel.
  128.     cmpi.w    #-16500,8(sp)    // we want to avoid -16500
  129.     bne        exitPatchPowerOff
  130. // if it's the alert we want, return to caller without 
  131. // executing the alert.  
  132. // FUNCTION Alert ( alertID: INTEGER; filterProc: ProcPtr) : INTEGER;
  133. // means that the stack looks like this:
  134. //        sp + 0 -> return address (4 bytes)
  135. //           + 4 -> filterProc (4 bytes)
  136. //           + 8 -> alertID (2 bytes)
  137.     movea.l    (sp)+, a0    // the caller's return address
  138.     lea        6(sp), sp    // clear off the parms put on by caller
  139.     move.w    #2, (sp)    // tell the system we hit cancel. (2nd button = cancel)
  140.     jmp        (a0)        // return to caller without actually calling Alert
  141.     
  142. exitPatchPowerOff:
  143.     // call the original trap.
  144. //First, set up a4 to access the old trap address
  145.     jsr        SetUpA4        // puts old a4 into register d0
  146.  
  147.     lea        gOriginalTrapPtr, a0
  148.  
  149.     exg        d0, a4        // restore old value of a4
  150.     
  151.     movea.l    (a0), a0
  152.     jmp        (a0)    
  153. }
  154.  
  155. /*
  156.  * DisablePowerOffKey
  157.  * This routine will either call the routine pointed to by the Gestalt
  158.  * selector 'pwky', telling it to disable the power off key, or this
  159.  * routine will return an error (usually telling you the Gestalt selector
  160.  * is not installed.)
  161.  */
  162. OSErr DisablePowerOffKey(void) 
  163. {
  164.     OSErr err;
  165.     PwrKeyProc pPwrKey;
  166.     err = Gestalt('pwky', (long*) &pPwrKey);
  167.     if ( (long) pPwrKey == nil )
  168.         err = gestaltUndefSelectorErr;    // no proc ptr means no selector
  169.     if ( err == noErr )
  170. #ifdef PowerPC
  171.         err = CallUniversalProc((UniversalProcPtr) pPwrKey,
  172.             uppPowerOffProcInfo, kPowerKey, kDissablePwKy);
  173. #else
  174.         err = pPwrKey(kPowerKey, kDissablePwKy);
  175. #endif
  176.     return err;
  177. }
  178.  
  179.  
  180. /* main */
  181.  
  182. void main(void)
  183. {
  184.     long    oldA4;
  185.     Handle    h;
  186.     OSErr    err = noErr;
  187.     
  188.     #ifdef USE_DEBUGGER_CALLS
  189.         Debugger();
  190.     #endif
  191.  
  192.     /* set up our A4 context for _this file_ */
  193.     oldA4 = SetCurrentA4();
  194.     RememberA4();
  195.         
  196.     /* First try to disable the power key programmatically.
  197.      * If that doesn't work, do a skanky hack.
  198.      */
  199.     if (DisablePowerOffKey() != noErr)
  200.     {
  201.         /* detach ourselves */
  202.         h = Get1Resource('INIT', kINITid);
  203.         if (h) DetachResource(h);
  204.             
  205.         InitAlertPatch();
  206.     }
  207.     ShowIcon7(kICONid, true);
  208.     
  209.     /* restore the a4 world */
  210.     SetA4(oldA4);
  211. }
  212.